package com.easylinkin.linkappapi.quality.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.service.OSSService;
import com.easylinkin.linkappapi.common.utils.NumberUtil;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.file.FileExt;
import com.easylinkin.linkappapi.common.utils.file.ZipFileUtil;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.facerecognition.service.oss.ObjectStorageInternalService;
import com.easylinkin.linkappapi.lobar.mapper.LaborCompanyProjectMapper;
import com.easylinkin.linkappapi.lobar.util.PercentageUtils;
import com.easylinkin.linkappapi.openapi.dto.LaborCountDTO;
import com.easylinkin.linkappapi.photoalbum.util.ExportUtil;
import com.easylinkin.linkappapi.quality.dto.*;
import com.easylinkin.linkappapi.quality.entity.QualityInspection;
import com.easylinkin.linkappapi.quality.entity.QualityQuestionDealRecord;
import com.easylinkin.linkappapi.quality.entity.QualityQuestionInfo;
import com.easylinkin.linkappapi.quality.entity.vo.QualityQuestionInfoVo;
import com.easylinkin.linkappapi.quality.entity.vo.QualityScreenPageVo;
import com.easylinkin.linkappapi.quality.mapper.QualityInspectionMapper;
import com.easylinkin.linkappapi.quality.mapper.QualityQuestionDealRecordMapper;
import com.easylinkin.linkappapi.quality.mapper.QualityQuestionInfoMapper;
import com.easylinkin.linkappapi.quality.service.QualityQuestionInfoService;
import com.easylinkin.linkappapi.quality.util.QualityMessageUtils;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.service.LinkappUserService;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * QualityQuestionInfo表服务实现类
 *
 * @author zhengwen
 * @date 2022/08/16
 */
@Slf4j
@Service("appQualityQuestionInfoService")
public class QualityQuestionInfoServiceImpl extends ServiceImpl
        <QualityQuestionInfoMapper, QualityQuestionInfo> implements QualityQuestionInfoService {
    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Autowired
    private QualityQuestionDealRecordMapper questionDealRecordMapper;
    @Autowired
    private QualityInspectionMapper qualityInspectionMapper;
  @Resource
  private LinkappUserService userService;

  @Resource
  private LinkappTenantMapper linkappTenantMapper;

  @Resource
  private LaborCompanyProjectMapper LaborCompanyProjectMapper;

    @Override
    public boolean saveOne(QualityQuestionInfo appQualityQuestionInfo) {
        commonService.setCreateAndModifyInfo(appQualityQuestionInfo);
        // appQualityQuestionInfo.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        validParamRequired(appQualityQuestionInfo);
        validRepeat(appQualityQuestionInfo);
        validParamFormat(appQualityQuestionInfo);
        return save(appQualityQuestionInfo);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOne(QualityQuestionInfo appQualityQuestionInfo) {
        Assert.notNull(appQualityQuestionInfo.getId(), "id不能为空");
        commonService.setModifyInfo(appQualityQuestionInfo);
        //appQualityQuestionInfo.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        validRepeat(appQualityQuestionInfo);
        validParamFormat(appQualityQuestionInfo);
        return updateById(appQualityQuestionInfo);
    }


  @Override
  public boolean modifyRectifyUser(QualityQuestionInfo appQualityQuestionInfo) {
    Assert.notNull(appQualityQuestionInfo.getId(), "id不能为空");
    Assert.notNull(appQualityQuestionInfo.getRectifierId(), "整改人id不能为空");
    QualityQuestionInfo old = baseMapper.getOneById(appQualityQuestionInfo.getId());
    Assert.isTrue(null != old, "质量问题不存在");
    Assert.isTrue(old.getQuestionState() == 1 || old.getQuestionState() == 4, "质量问题状态不为待整改");
    LinkappUser rectifyUser = userService
        .findById(appQualityQuestionInfo.getRectifierId().longValue());
    if (null != rectifyUser) {
      appQualityQuestionInfo.setRectifierName(rectifyUser.getNickname());
    }
    LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
    appQualityQuestionInfo.setModifier(String.valueOf(linkappUser.getId()));
    appQualityQuestionInfo.setModifyTime(DateUtil.date());
    if (updateById(appQualityQuestionInfo)) {
      // 发送消息提醒整改人整改
      QualityMessageUtils.saveMessage("整改", appQualityQuestionInfo.getRectifierId() + "",
          appQualityQuestionInfo.getId(), true);
      return true;
    }
    return false;
  }

  @Override
  public boolean modifyCheckUser(QualityQuestionInfo appQualityQuestionInfo) {
    Assert.notNull(appQualityQuestionInfo.getId(), "id不能为空");
    Assert.notNull(appQualityQuestionInfo.getReviewerId(), "复查人id不能为空");
    QualityQuestionInfo old = baseMapper.getOneById(appQualityQuestionInfo.getId());
    Assert.isTrue(null != old, "隐患不存在");
    Assert.isTrue(
        old.getQuestionState() == 1 || old.getQuestionState() == 2 || old.getQuestionState() == 4,
        "隐患状态不为待复查");
    LinkappUser reviewerUser = userService
        .findById(appQualityQuestionInfo.getReviewerId().longValue());
    if (null != reviewerUser) {
      appQualityQuestionInfo.setReviewerName(reviewerUser.getNickname());
    }
    LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
    appQualityQuestionInfo.setModifier(String.valueOf(linkappUser.getId()));
    appQualityQuestionInfo.setModifyTime(DateUtil.date());
    if (updateById(appQualityQuestionInfo)) {
      if (old.getQuestionState() == 2) {
        // 给复查人发送复查消息
        QualityMessageUtils.saveMessage("复查", appQualityQuestionInfo.getReviewerId() + "",
            appQualityQuestionInfo.getId(), true);
      }
      return true;
    }
    return false;
  }

    @Override
    public RestMessage laborQuestionRanking(QualityScreenPageVo qualityScreenPageVo) {
        String queryType = qualityScreenPageVo.getQueryType();
        if (StringUtils.isBlank(queryType)) {
            queryType = "7d";
        }
        Date startTime = qualityScreenPageVo.getStartTime();
        Date endTime = qualityScreenPageVo.getEndTime();
        if(startTime == null && endTime == null){
            endTime = DateUtil.endOfDay(DateUtil.date());
        }
        switch(queryType){
            case "30d":
                startTime = DateUtil.beginOfDay(DateUtil.offsetDay(endTime,-29));
                break;
            case "sm":
                startTime = DateUtil.beginOfDay(DateUtil.offsetMonth(endTime,-5));
                break;
            case "7d":
                startTime = DateUtil.beginOfDay(DateUtil.offsetDay(endTime, -6));
                break;
            default:
                break;
        }
        qualityScreenPageVo.setStartTime(startTime);
        qualityScreenPageVo.setEndTime(endTime);

        List<LaborCountDTO> ls = new ArrayList<>();
        List<Map<String,Object>> countLs = baseMapper.questionCountGroupByLabor(qualityScreenPageVo);
        if(CollectionUtil.isNotEmpty(countLs)){
            //查询参加项目数量
            Map<String,Integer> subNumMp = new HashMap<>();
            List<Map<String,Object>> subNumMpLs = LaborCompanyProjectMapper.querySubAddProjectNum();
            if(CollectionUtil.isNotEmpty(subNumMpLs)){
                //转map
                subNumMpLs.stream().forEach(s->{
                    Object id = s.get("id");
                    Object num = s.get("num");
                    subNumMp.put(id.toString(), Integer.valueOf(num.toString()));
                });
            }

            Map<String,LaborCountDTO> dtoMp = new HashMap<>();
            //循环计算
            for (int i = 0;i < countLs.size();i++){
                Map<String,Object> cp = countLs.get(i);
                LaborCountDTO dto = initLaborCountDTO(cp,dtoMp,subNumMp);
                //ls.add(dto);
            }
            ls = dtoMp.values().stream().collect(Collectors.toList());
        }
        if(CollectionUtil.isNotEmpty(ls)){
            //排序
            ls = ls.stream().sorted(Comparator.comparing(LaborCountDTO::getRectRate).reversed()).collect(Collectors.toList());
        }
        //加一层逻辑处理最终数据
        List<LaborCountDTO> finLs = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(ls)){
            for(LaborCountDTO dto:ls){
                Integer totalNum = dto.getTotalNum();
                if(totalNum != null && totalNum.intValue() > 0){
                    if(finLs.size() <= 14){
                        finLs.add(dto);
                    }else{
                        break;
                    }
                }
            }
        }

        return RestBuilders.successBuilder().data(finLs).build();
    }

    private LaborCountDTO initLaborCountDTO(Map<String, Object> c, Map<String, LaborCountDTO> dtoMp, Map<String, Integer> subNumMp) {
        String subOrgId = c.get("id").toString();
        LaborCountDTO dto = dtoMp.get(subOrgId);
        Integer subProjectNum = subNumMp.get(subOrgId);
        if(dto == null){
            dto = new LaborCountDTO();
            if(subProjectNum == null){
                subProjectNum = 0;
            }
            dto.setProjectNum(subProjectNum);
            dto.setId(subOrgId);

            String subCompanyName = c.get("subCompanyName").toString();
            dto.setSubOrgName(subCompanyName);
        }
        Object questionState = c.get("questionState");
        if(questionState != null){
            int num = 0;
            Object numObj = c.get("num");
            if(numObj == null){
                num = 0;
            }else{
                num = Integer.parseInt(numObj.toString());
            }
            //问题状态，1待整改、2待复核、3合格,4不合格
            if(Integer.valueOf(questionState.toString()).intValue() == 3){
                dto.setRectNum(num);
            }
            dto.setTotalNum(dto.getTotalNum() + num);

            if(dto.getTotalNum() != null && dto.getTotalNum().intValue() != 0){
                BigDecimal rate = cn.hutool.core.util.NumberUtil.div(dto.getRectNum(),dto.getTotalNum(),4);
                rate = cn.hutool.core.util.NumberUtil.mul(rate,new BigDecimal(100));
                dto.setRectRate(rate);
            }

        }
        dtoMp.put(subOrgId,dto);
        return dto;
    }

    @Override
    public IPage<QualityQuestionInfo> selectPage(Page page, QualityQuestionInfo appQualityQuestionInfo) {
        //appQualityQuestionInfo.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.selectPage(page, appQualityQuestionInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> idList) {
        return removeByIds(idList);
    }

    @Override
    public void export(QualityQuestionInfo appQualityQuestionInfo, HttpServletRequest request, HttpServletResponse
            response) {

        IPage<QualityQuestionInfo> page = selectPage(new Page(0, -1), appQualityQuestionInfo);
        List<QualityQuestionInfo> records = page.getRecords();
        List
                <QualityQuestionInfoVo> appQualityQuestionInfoVos = new ArrayList<>();
        for (QualityQuestionInfo expert : records) {
            appQualityQuestionInfoVos.add(new QualityQuestionInfoVo(expert));
        }

        String keyValue = "名称:name,租户id:tenantId";
        String title = "QualityQuestionInfo导出数据";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                .getOutputStream(request, response, fileName);
            ExcelTools.exportExcel(outputStream, keyValue, appQualityQuestionInfoVos, ExcelConstant.XLS, title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }
    }

    @Override
    public RestMessage saveQuestion(QualityQuestionInfoVo qualityQuestionInfoVo) {
        LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
        //参数校验
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getCheckPartId() == null, "检查部位不能为空");
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getQuestionDescribeId() == null, "问题描述不能为空");
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getQuestionLevel() == null, "问题等级不能为空");
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getUrgentLevel() == null, "问题紧急程度不能为空");
        //cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getRectifiLimitTime() == null, "整改时限不能为空");

        cn.hutool.core.lang.Assert.isFalse(StringUtils.isBlank(qualityQuestionInfoVo.getRectifiTarget()), "整改要求不能为空");
        cn.hutool.core.lang.Assert.isFalse(StringUtils.isBlank(qualityQuestionInfoVo.getMemo()), "补充说明不能为空");
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getRectifierId() == null, "问题整改人不能为空");
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getReviewerId() == null, "问题复核人不能为空");
        cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfoVo.getReviewLimitTime() == null, "复核时限不能为空");

        //整改时限为空就后端计算
        if(qualityQuestionInfoVo.getRectifiLimitTime() == null){
            //整改时限计算
            Integer changeLimit = qualityQuestionInfoVo.getChangeLimit();
            cn.hutool.core.lang.Assert.isFalse(changeLimit == null, "整改时限不能为空");
            Date rectifiLimitTime = DateUtil.offsetDay(DateUtil.date(), changeLimit);
            qualityQuestionInfoVo.setRectifiLimitTime(DateUtil.endOfDay(rectifiLimitTime));
        }

        Long id = qualityQuestionInfoVo.getId();
        if (id == null) {
            //新增
            QualityQuestionInfo qualityQuestionInfo = new QualityQuestionInfo();
            BeanUtil.copyProperties(qualityQuestionInfoVo, qualityQuestionInfo, CopyOptions.create().setIgnoreNullValue(true));
            qualityQuestionInfo.setTenantId(linkappUser.getTenantId());
            qualityQuestionInfo.setCreator(String.valueOf(linkappUser.getId()));
            qualityQuestionInfo.setCreateTime(DateUtil.date());
            qualityQuestionInfo.setDeleteState(1);
            qualityQuestionInfo.setQuestionState(1);

            //规避传参23:59:59导致跨天
            qualityQuestionInfo.setRectifiLimitTime(DateUtil.endOfDay(qualityQuestionInfoVo.getRectifiLimitTime()).offset(DateField.MILLISECOND,-999));
            qualityQuestionInfo.setReviewLimitTime(DateUtil.endOfDay(qualityQuestionInfoVo.getReviewLimitTime()).offset(DateField.MILLISECOND,-999));
            //整改时限不能晚于复核时限
            cn.hutool.core.lang.Assert.isFalse(qualityQuestionInfo.getReviewLimitTime().before(qualityQuestionInfo.getRectifiLimitTime()), "复核时限不能早于整改时限");
            this.baseMapper.insert(qualityQuestionInfo);
            id = qualityQuestionInfo.getId();
            //记录消息
            QualityMessageUtils.saveMessage("整改",qualityQuestionInfo.getRectifierId()+"", qualityQuestionInfo.getId(),true);
            if (StringUtils.isNotBlank(qualityQuestionInfo.getNoticerIds())){
                String[] strings = qualityQuestionInfo.getNoticerIds().split(",");
                Arrays.stream(strings).forEach(s ->{
                    QualityMessageUtils.saveMessage("整改",s, qualityQuestionInfo.getId(),true);
                });
            }
        } else {
            //修改
            QualityQuestionInfo dbQueInfo = this.baseMapper.selectById(id);
            if (dbQueInfo == null) {
                RestBuilders.errorBuilder().message("数据不存在").build();
            }
            BeanUtil.copyProperties(qualityQuestionInfoVo, dbQueInfo, CopyOptions.create().setIgnoreNullValue(true));
            dbQueInfo.setModifier(String.valueOf(linkappUser.getId()));
            dbQueInfo.setModifyTime(DateUtil.date());
            this.baseMapper.updateById(dbQueInfo);
        }
        Map<String,Object> map = new HashMap<>();
        map.put("id",id);
        return RestBuilders.successBuilder().data(map).build();
    }

    @Override
    public QualityQuestionInfo getOneById(Serializable id) {
        return baseMapper.getOneById(id);
    }

    /**
     * @Description: 质量问题分类统计
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<QualityScreenDTO> getByProblemType(QualityScreenDTO qualityScreenDTO) {
        qualityScreenDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<QualityScreenDTO> qualityScreenDTOS = baseMapper.getByProblemType(qualityScreenDTO);
        qualityScreenDTOS.forEach(q -> {
            String name = q.getName();
            if (StringUtils.isNotBlank(name)){
                q.setName(name.substring(0, name.indexOf("/")));
            }
        });
        return qualityScreenDTOS;
    }

    /**
     * @Description: 整改率统计
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<String> dealRecord(List<Long> questionInfoIds) {
        List<String> result = new ArrayList<>();
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //查询所有问题
        QueryWrapper<QualityQuestionInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("tenant_id", tenantId).eq("delete_state", 1);
        queryWrapper1.in(CollectionUtil.isNotEmpty(questionInfoIds),"id",questionInfoIds);
        List<QualityQuestionInfo> questionInfoList = baseMapper.selectList(queryWrapper1);
        //查询整改记录
        List<QualityQuestionDealRecord> dealRecords = questionDealRecordMapper.findByTenantId(tenantId);
        if (CollectionUtil.isNotEmpty(questionInfoIds)){
            dealRecords = dealRecords.stream().filter(d->questionInfoIds.contains(d.getQuestionId()))
                    .collect(Collectors.toList());
        }
        //过滤
        Map<Long, List<QualityQuestionDealRecord>> map = dealRecords.stream()
                .collect(Collectors.groupingBy(QualityQuestionDealRecord::getQuestionId));
        //整改及时率
        AtomicInteger re = new AtomicInteger();
        map.forEach((k, v) -> {
            //v按时间升序排列
            v = v.stream().sorted(Comparator.comparingLong(t -> t.getDealTime().getTime())).
                    collect(Collectors.toList());
            QualityQuestionDealRecord record = v.get(0);
            //与问题时间对比
            long count = questionInfoList.stream().filter(
                            q -> k.equals(q.getId()) && q.getRectifiLimitTime().getTime() >= record
                                    .getDealTime().getTime())
                    .count();
            if (count > 0) {
                re.getAndIncrement();
            }
        });
        result.add(PercentageUtils.computePercentOne(re.get(), questionInfoList.size()));

        //查询整改成功率
        long size = questionInfoList.stream()
                .filter(q -> Integer.valueOf(3).equals(q.getQuestionState())).count();
        result.add(PercentageUtils.computePercentOne((int) size, questionInfoList.size()));

        //整改总次数
        result.add(dealRecords.size() + "");
        return result;
    }

    /**
     * @Description: 统计概览
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<Integer> overview() {
        List<Integer> result = new ArrayList<>();
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //所有问题数 + 巡检记录
        //查询所有问题
        QueryWrapper<QualityQuestionInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("tenant_id", tenantId).eq("delete_state", 1);
        List<QualityQuestionInfo> questionInfoList = baseMapper.selectList(queryWrapper1);
        //巡检记录数
        QueryWrapper<QualityInspection> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("tenant_id_", tenantId);
        Integer integer = qualityInspectionMapper.selectCount(queryWrapper2);
        //全部
        result.add(questionInfoList.size() + integer);

        //待整改
        result.add(this.overviewCount(questionInfoList, 1));

        //无需整改
        //质量问题中状态为无需整改的数据
        result.add(integer+this.overviewCount(questionInfoList, 5));

        //待复查
        result.add(this.overviewCount(questionInfoList, 2));

        //合格
        result.add(this.overviewCount(questionInfoList, 3));

        //不合格
        result.add(this.overviewCount(questionInfoList, 4));
        return result;
    }

    @Override
    public RestMessage selectDtoOne(Long id) {
        QualityQuestionInfoDto dto = baseMapper.selectDtoOne(id);
        if (Integer.valueOf(0).equals(dto.getDeleteState())){
            throw new BusinessException("该数据已被删除");
        }
        return RestBuilders.successBuilder().data(dto).build();
    }

    @Override
    public RestMessage selectDtoOneFromEnterprise(Long id) {
        QualityQuestionInfoDto dto = baseMapper.selectDtoOne(id);
        if (Integer.valueOf(0).equals(dto.getDeleteState())){
            throw new BusinessException("该数据已被删除");
        }
        return RestBuilders.successBuilder().data(dto).build();
    }

    @Override
    public RestMessage getTabCountNum(QualityQuestionInfoVo questionInfoVo) {
        Map<String, Integer> mp = new HashMap<>();
        mp.put("all", 0);
        mp.put("waitDeal", 0);
        mp.put("deal", 0);
        LinkappUser appUser = linkappUserContextProducer.getNotNullCurrent();
        questionInfoVo.setTenantId(appUser.getTenantId());
        String dataType = questionInfoVo.getDataType();
        cn.hutool.core.lang.Assert.isFalse(StringUtils.isBlank(dataType), "tab数据类型为空");

        Map<String,String> numMp = new HashMap<>();
        switch (dataType) {
            case "rectifiNum":
                questionInfoVo.setRectifierId(appUser.getId().intValue());
                List<Map<String, Object>> rectifiNumMp = this.baseMapper.countNumByState(questionInfoVo);
                //1待整改、2待复核、3合格，4不合格
                if (CollectionUtil.isNotEmpty(rectifiNumMp)) {
                    rectifiNumMp.stream().forEach(n->{
                        Object questionStateObj = n.get("questionState");
                        Object numObj = n.get("num");
                        numMp.put(questionStateObj.toString(),numObj.toString());
                    });
                    Integer waitDeal = (numMp.get("1") == null ? 0 : Integer.parseInt(numMp.get("1"))) + (numMp.get("4") == null ? 0 : Integer.parseInt(numMp.get("4")));
                    Integer deal = (numMp.get("2") == null ? 0 : Integer.parseInt(numMp.get("2"))) + (numMp.get("3") == null ? 0 : Integer.parseInt(numMp.get("3")));
                    mp.put("waitDeal",waitDeal);
                    mp.put("deal",deal);
                    mp.put("all",waitDeal + deal);
                }
                break;
            case "reviewNum":
                questionInfoVo.setReviewerId(appUser.getId().intValue());
                List<Map<String, Object>> reviewNumMp = this.baseMapper.countNumByState(questionInfoVo);
                //1待整改、2待复核、3合格，4不合格
                if (CollectionUtil.isNotEmpty(reviewNumMp)) {
                    reviewNumMp.stream().forEach(n->{
                        Object questionStateObj = n.get("questionState");
                        Object numObj = n.get("num");
                        numMp.put(questionStateObj.toString(),numObj.toString());
                    });
                    Integer waitDeal = (numMp.get("2") == null ? 0 : Integer.parseInt(numMp.get("2")));
                    Integer deal = (numMp.get("3") == null ? 0 : Integer.parseInt(numMp.get("3"))) + (numMp.get("4") == null ? 0 : Integer.parseInt(numMp.get("4")));
                    mp.put("waitDeal",waitDeal);
                    mp.put("deal",deal);
                    mp.put("all",waitDeal + deal);
                }
                break;
            default:
                break;
        }

        return RestBuilders.successBuilder().data(mp).build();
    }

    @Override
    public IPage<QualityQuestionInfoDto> selectDtoPage(Page page, QualityQuestionInfoVo questionInfoVo) {
        LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
        questionInfoVo.setTenantId(linkappUser.getTenantId());

        Boolean onlySelf = questionInfoVo.getOnlySelf();
        if (onlySelf != null && onlySelf) {
            questionInfoVo.setCreator(String.valueOf(linkappUser.getId()));
        }

        String dataType = questionInfoVo.getDataType();
        if (StringUtils.isNotBlank(dataType)){
            switch (dataType) {
                case "rectifiNum":
                    questionInfoVo.setRectifierId(linkappUser.getId().intValue());
                    break;
                case "reviewNum":
                    questionInfoVo.setReviewerId(linkappUser.getId().intValue());
                    break;
                default:
                    break;
            }
        }

        IPage<QualityQuestionInfoDto> iPage = baseMapper.selectDtoPage(page, questionInfoVo);
        //处理
        Date now = DateUtil.date();
        iPage.getRecords().forEach(r -> {
            //问题都是type=1
            r.setType(1);
            Date rectifiLimitTime = r.getRectifiLimitTime();
            Date reviewLimitTime = r.getReviewLimitTime();

            List<QualityQuestionDealRecord> dealRecordList = r.getDealRecordList();
            if (CollectionUtil.isNotEmpty(dealRecordList)) {
                QualityQuestionDealRecord rectifi = dealRecordList.stream().filter(f -> f.getDealType().intValue() == 1).findFirst().orElse(null);
                if (rectifi != null) {
                    if (rectifi.getDealTime().after(rectifiLimitTime)) {
                        r.setRectifiAfter(true);
                    } else {
                        r.setRectifiAfter(false);
                    }
                }else {
                    if (rectifiLimitTime.before(now)) {
                        r.setRectifiAfter(true);
                    }
                }
                QualityQuestionDealRecord review = dealRecordList.stream().filter(f -> f.getDealType().intValue() == 2).findFirst().orElse(null);
                if (review != null) {
                    if (review.getDealTime().after(reviewLimitTime)) {
                        r.setReviewAfter(true);
                    } else {
                        r.setReviewAfter(false);
                    }
                }else {
                    if (reviewLimitTime.before(now)) {
                        r.setReviewAfter(true);
                    }
                }
            } else {
                if (rectifiLimitTime.before(now)) {
                    r.setRectifiAfter(true);
                } else {
                    r.setRectifiAfter(null);
                }
                if (reviewLimitTime.before(now)) {
                    r.setReviewAfter(true);
                } else {
                    r.setReviewAfter(null);
                }
            }
        });

        return iPage;
    }

    @Override
    public IPage<QualityQuestionInfoDto> selectDtoPageFromEnterprise(Page page, QualityQuestionInfoVo questionInfoVo) {
        // 需求去掉的筛选项
//        LinkappUser linkappUser = null;

//        Boolean onlySelf = questionInfoVo.getOnlySelf();
//        if (onlySelf != null && onlySelf && linkappUser != null) {
//            questionInfoVo.setCreator(String.valueOf(linkappUser.getId()));
//        }

//        String dataType = questionInfoVo.getDataType();
//        if (StringUtils.isNotBlank(dataType) && linkappUser != null) {
//            switch (dataType) {
//                case "rectifiNum":
//                    questionInfoVo.setRectifierId(linkappUser.getId().intValue());
//                    break;
//                case "reviewNum":
//                    questionInfoVo.setReviewerId(linkappUser.getId().intValue());
//                    break;
//                default:
//                    break;
//            }
//        }


        // 处理projectIds 项目过滤 用户所拥有权限的项目下的数据
        Set<Long> projectIds = questionInfoVo.getProjectIds();
        if (ObjectUtils.isEmpty(projectIds)) {
            return page;
        }
        List<LinkappTenant> tenants2 = linkappTenantMapper.selectByProjectIds(projectIds);
        Set<String> tenantIds2 = tenants2.stream().map(LinkappTenant::getId).collect(Collectors.toSet());
        if (ObjectUtils.isEmpty(tenantIds2)) {
            return page;
        }
        questionInfoVo.setTenantIds(tenantIds2);

        // 处理projectId 项目过滤
        if (questionInfoVo.getProjectId() != null) {
            List<LinkappTenant> tenants = linkappTenantMapper.selectByProjectId(String.valueOf(questionInfoVo.getProjectId()));
            if (tenants.size() == 0) {
                return page;
            } else {
                questionInfoVo.setTenantId(tenants.get(0).getId());
            }
        }

        IPage<QualityQuestionInfoDto> iPage = baseMapper.selectDtoPage(page, questionInfoVo);
        Set<String> tenantIds = iPage.getRecords().stream().map(QualityQuestionInfoDto::getTenantId).collect(Collectors.toSet());
        List<LinkappTenant> tenants = linkappTenantMapper.selectProjectNamesByTenantIds(tenantIds);
        Map<String, List<LinkappTenant>> map = tenants.stream().collect(Collectors.groupingBy(LinkappTenant::getId));

        //处理
        Date now = DateUtil.date();
        iPage.getRecords().forEach(r -> {
            // 设置项目名称
            List<LinkappTenant> list = map.get(r.getTenantId());
            if (list != null && list.size() != 0) {
                r.setProjectName(list.get(0).getPlatformProjectName());
            }

            Date rectifiLimitTime = r.getRectifiLimitTime();
            Date reviewLimitTime = r.getReviewLimitTime();

            List<QualityQuestionDealRecord> dealRecordList = r.getDealRecordList();
            if (CollectionUtil.isNotEmpty(dealRecordList)) {
                QualityQuestionDealRecord rectifi = dealRecordList.stream().filter(f -> f.getDealType().intValue() == 1).findFirst().orElse(null);
                if (rectifi != null) {
                    if (rectifi.getDealTime().after(rectifiLimitTime)) {
                        r.setRectifiAfter(true);
                    } else {
                        r.setRectifiAfter(false);
                    }
                }else {
                    if (rectifiLimitTime.before(now)) {
                        r.setRectifiAfter(true);
                    }
                }
                QualityQuestionDealRecord review = dealRecordList.stream().filter(f -> f.getDealType().intValue() == 2).findFirst().orElse(null);
                if (review != null) {
                    if (review.getDealTime().after(reviewLimitTime)) {
                        r.setReviewAfter(true);
                    } else {
                        r.setReviewAfter(false);
                    }
                }else {
                    if (reviewLimitTime.before(now)) {
                        r.setReviewAfter(true);
                    }
                }
            } else {
                if (rectifiLimitTime.before(now)) {
                    r.setRectifiAfter(true);
                } else {
                    r.setRectifiAfter(null);
                }
                if (reviewLimitTime.before(now)) {
                    r.setReviewAfter(true);
                } else {
                    r.setReviewAfter(null);
                }
            }
        });

        return iPage;
    }

    /**
     * @Description: 分包单位统计
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<QualityScreenDTO> getBySubOrg() {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //查询全部问题
        List<QualityQuestionInfoVo> questionInfoList = baseMapper.getBySubOrg(tenantId);
        //查询整改记录
        List<QualityQuestionDealRecord> dealRecords = questionDealRecordMapper.findByTenantId(tenantId);
        questionInfoList.forEach(q -> {
            //求是否及时整改
            long count = dealRecords.stream().filter(d -> q.getId().equals(d.getQuestionId())
                            && d.getDealTime().getTime() <= q.getRectifiLimitTime().getTime())
                    .count();
            if (count > 0) {
                q.setTimelyChange(true);
            }
        });
        List<QualityScreenDTO> result = new ArrayList<>();
        Map<String, List<QualityQuestionInfoVo>> map = questionInfoList.stream()
                .collect(Collectors.groupingBy(QualityQuestionInfoVo::getSubOrgId));
        map.forEach((k, v) -> {
            QualityScreenDTO qualityScreenDTO = new QualityScreenDTO();
            qualityScreenDTO.setName(v.get(0).getSubOrgName());
            qualityScreenDTO.setNumber(v.size());
            long common = v.stream().filter(va -> Integer.valueOf(1).equals(va.getUrgentLevel())).count();
            qualityScreenDTO.setCommon((int) common);
            long serious = v.stream().filter(va -> Integer.valueOf(2).equals(va.getUrgentLevel())).count();
            qualityScreenDTO.setSerious((int) serious);
            long urgent = v.stream().filter(va -> Integer.valueOf(3).equals(va.getUrgentLevel())).count();
            qualityScreenDTO.setUrgent((int) urgent);
            //及时整改数量
            long count = v.stream().filter(va -> va.isTimelyChange()).count();
            DecimalFormat df1 = new DecimalFormat("0.0");
            float f = ((float) count / (float) v.size()) * 100;
            qualityScreenDTO.setPartNum(f);
            qualityScreenDTO.setPart(df1.format(f) + "%");
            result.add(qualityScreenDTO);
        });
        //按及时率倒序
        List<QualityScreenDTO> dtoList = result.stream()
            .sorted(Comparator.comparing(QualityScreenDTO::getPartNum).reversed())
            .collect(Collectors.toList());
        if (dtoList.size()>10){
            return dtoList.subList(0,10);
        }else {
            return dtoList;
        }
    }

    /**
     * @Description: 查询一个月内的数据
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<QualityScreenDTO> getByMonth() {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //一个月内新增问题数
        List<QualityScreenDTO> qualityScreenDTOS = baseMapper.getByMonth(tenantId);
        //一个月内整改问题数
        List<QualityScreenDTO> recordDTOS = questionDealRecordMapper.getByMonth(tenantId);

        //组织一个月的数据
        List<QualityScreenDTO> result = new ArrayList<>();
        for (int i = 29; i >= 0; i--) {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -i);
            QualityScreenDTO qualityScreenDTO = new QualityScreenDTO();
            qualityScreenDTO.setStartTime(calendar.getTime());
            //新增数量
            List<QualityScreenDTO> screenDTOList = qualityScreenDTOS.stream().filter(q ->
                            DateUtil.beginOfDay(calendar).getTime()
                                    .equals(DateUtil.beginOfDay(q.getStartTime())))
                    .collect(Collectors.toList());
            if (screenDTOList.size() > 0) {
                qualityScreenDTO.setNumber(screenDTOList.get(0).getNumber());
            }
            //整改数量
            List<QualityScreenDTO> screenDTOS = recordDTOS.stream()
                    .filter(q -> DateUtil.beginOfDay(calendar).getTime()
                            .equals(DateUtil.beginOfDay(q.getStartTime())))
                    .collect(Collectors.toList());
            if (screenDTOS.size() > 0) {
                qualityScreenDTO.setChangeNum(screenDTOS.get(0).getChangeNum());
            }
            result.add(qualityScreenDTO);
        }
        return result;
    }

    /**
     * 问题统计
     *
     * @param
     */
    private Integer overviewCount(List<QualityQuestionInfo> questionInfoList, Integer questionState) {
        long count = questionInfoList.stream()
                .filter(q -> questionState.equals(q.getQuestionState())).count();
        return (int) count;
    }

    /**
     * 校验重复
     */
    private void validRepeat(QualityQuestionInfo appQualityQuestionInfo) {
        /* QueryWrapper<QualityQuestionInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", appQualityQuestionInfo.getName());
        queryWrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<QualityQuestionInfo> list = baseMapper.selectList(queryWrapper);
        if (list.size() == 0) {
            return;
        }
        if (list.size() > 1) {
            throw new BusinessException("名称有重复");
        }
        if (ObjectUtils.isEmpty(appQualityQuestionInfo.getId())) {
            throw new BusinessException("名称已存在");
        }
        if (!appQualityQuestionInfo.getId().equals(list.get(0).getId())) {
            throw new BusinessException("名称已存在");
        }
                    */

    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(QualityQuestionInfo appQualityQuestionInfo) {
        //Assert.notNull(appQualityQuestionInfo, "参数为空");
        //Assert.isTrue(StringUtils.isNotBlank(appQualityQuestionInfo.getName()), "名称为空");
    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(QualityQuestionInfo appQualityQuestionInfo) {
        //Assert.isTrue(appQualityQuestionInfo.getName() == null || appQualityQuestionInfo.getName().length() <= 50,
        //        "名称超长");
    }

    @Override
    public IPage<QualityQuestionPhotoAlbumDTO> selectPhotoAlbumByPage(Page page,
        QualityQuestionPhotoAlbumQueryDTO queryDTO) {
        queryDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        IPage<QualityQuestionPhotoAlbumDTO> pagelist = baseMapper
            .selectPhotoAlbumByPage(page, queryDTO);
        pagelist.getRecords().forEach(p->setPhotos(p));
        return pagelist;
    }

    private void setPhotos(QualityQuestionPhotoAlbumDTO dto){
        List<String> photos = new ArrayList<>();
        String imgs = dto.getImgs();
        String dealImgs = dto.getDealImgs();
        if(StringUtils.isNotEmpty(imgs)){
            photos.addAll(Arrays.asList(imgs.split(",")));
        }
        if(StringUtils.isNotEmpty(dealImgs)){
            photos.addAll(Arrays.asList(dealImgs.split(",")));
        }
        dto.setPhotos(photos);
    }

    @Override
    public int photoAlbumCount(QualityQuestionPhotoAlbumQueryDTO queryDTO) {
        //项目id 过滤
        queryDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<QualityQuestionPhotoAlbumDTO> list = baseMapper
            .selectPhotoAlbumByPage(queryDTO);
        int total = 0;
        if(CollectionUtil.isNotEmpty(list)){
            for (QualityQuestionPhotoAlbumDTO dto : list) {
                setPhotos(dto);
                if(CollectionUtil.isNotEmpty(dto.getPhotos())){
                    total += dto.getPhotos().size();
                }
            }
        }
        return total;
    }

    @Autowired
    @Qualifier("ossInternal")
    private ObjectStorageInternalService ossClient;

    @Autowired
    private OSSService ossService;

    @Value("${oss.dir}")
    private String dir;

    @Value("${oss.bucket}")
    private String bucket;

    @Value("${oss.readHost}")
    private String readHost;

    private final String prefix = "质量问题";

    @Override
    public String exportPhotoAlbum(QualityQuestionPhotoAlbumQueryDTO dto) {
        //项目id 过滤
        dto.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        String fileName = null;
        List<QualityQuestionPhotoAlbumDTO> list = baseMapper
            .selectPhotoAlbumByPage(dto);

        List<FileExt> fileExtList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(list)){

            int total = 0;
            if(CollectionUtil.isNotEmpty(list)){
                for (QualityQuestionPhotoAlbumDTO p : list) {
                    setPhotos(p);
                    if(CollectionUtil.isNotEmpty(p.getPhotos())){
                        total += p.getPhotos().size();
                    }
                }
            }
            if(total > 100){
                throw new RuntimeException("相册导出失败！相册导出不能超过100张");
            }

            for (QualityQuestionPhotoAlbumDTO p : list) {
                List<String> photos = p.getPhotos();
                if (CollectionUtil.isNotEmpty(photos)) {
                    List<String> fileUrlList = new ArrayList<>();
                    for (int i = 0; i < photos.size(); i++) {
                        String singleFile = photos.get(i);
                        fileUrlList.add(singleFile);
                    }
                    long count = 0;
                    for (String url : fileUrlList) {

                        if (StringUtils.isNotEmpty(url)) {
                            url = url.replace("+", "%2B");
                            url = url.replace("&", "%26");
                        } else {
                            log.error("打包失败：名称为空");
                            continue;
                        }
                        FileExt fileInfoByUrl = ExportUtil
                            .getFileInfoByUrl(url,prefix, com.easylinkin.linkappapi.common.utils.DateUtil.getyyyyMMddHHmmssSSSNumberString(p.getCreateTime()),p.getProblemFullName(),count);
                        if (null != fileInfoByUrl && null != fileInfoByUrl.getInputStream()) {
                            fileExtList.add(fileInfoByUrl);
                            count ++;
                        } else {
                            log.error("打包失败：名称【{}】", url);
                        }
                    }
                }
            }

        }


        //开始导出
        InputStream fileInputStream = null;
        try {
            String today = com.easylinkin.linkappapi.common.utils.DateUtil.getyyyyMMddHHmmssSSSNumberString(new Date());
            fileInputStream = ZipFileUtil.getFileInputStream(today, fileExtList);
            //上传文件到oss
            String resultFilename =
                 prefix + "_" + today + ".zip";
            ossClient.putObject(bucket, resultFilename, fileInputStream, "application/octet-stream");
            fileName = ossService.generateUrl(resultFilename);
        } catch (Exception e) {
            log.error("打包失败：", e);
        } finally {
            // 关闭流
            try {
                if (null != fileInputStream) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                log.error("打包失败：", e);
            }
        }
        return fileName;
    }

    @Override
    public RestMessage countQualityQuestionByType(Page page, QualityQuestionStatisticsQueryDTO queryDTO) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        queryDTO.setTenantId(tenantId);
        if(queryDTO.getType() == 0){
            return RestBuilders.successBuilder()
                .data(baseMapper.countQualityQuestionBySubOrg(page, queryDTO)).build();
        }else if(queryDTO.getType() == 1){
            IPage<QualityQuestionStatisticsByProblemTypeDTO> dtos = baseMapper
                .countQualityQuestionByProblemType(page, queryDTO);
            if(CollectionUtil.isNotEmpty(dtos.getRecords())){
                dtos.getRecords().stream().forEach(p->{
                    if(null == p.getPercent()){
                        p.setPercent(0d);
                    }else{
                        p.setPercent(NumberUtil.mul(p.getPercent(),100d,2));
                    }
                });
            }
            return RestBuilders.successBuilder().data(dtos).build();
        }else {
            IPage<QualityQuestionStatisticsByCheckPartDTO> dtos = baseMapper
                .countQualityQuestionByCheckPart(page, queryDTO);
            if(CollectionUtil.isNotEmpty(dtos.getRecords())){
                dtos.getRecords().stream().forEach(p->{
                    if(null == p.getPercent()){
                        p.setPercent(0d);
                    }else{
                        p.setPercent(NumberUtil.mul(p.getPercent(),100d,2));
                    }
                });
            }
            return RestBuilders.successBuilder().data(dtos).build();
        }
    }

    @Override
    public void exportCountQualityQuestionByType(QualityQuestionStatisticsQueryDTO queryDTO,
        HttpServletRequest request, HttpServletResponse response) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        queryDTO.setTenantId(tenantId);
        if(queryDTO.getType() == 0){
            IPage<QualityQuestionStatisticsBySubOrgDTO> page = baseMapper
                .countQualityQuestionBySubOrg(new Page(0, -1), queryDTO);
            List<QualityQuestionStatisticsBySubOrgDTO> records = page.getRecords();
            String keyValue = "分包单位:subOrgName,班组:subGroupName,全部:allCount,一般:level1Count,严重:level2Count,紧要:level3Count,合格:state3";
            String title = "按分包单位/班组统计 导出数据";
            String fileName = title + ".xls";
            try {
                OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
                ExcelTools.exportExcel(outputStream, keyValue, records, ExcelConstant.XLS, title);
                response.flushBuffer();
                outputStream.close();
            } catch (IOException e) {
                log.error("excel导出失败", e);
                throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
            } catch (Exception e) {
                log.error("excel导出失败", e);
                throw new RuntimeException("excel导出失败！" + e.getMessage());
            }
        }else if(queryDTO.getType() == 1){
            IPage<QualityQuestionStatisticsByProblemTypeDTO> page = baseMapper
                .countQualityQuestionByProblemType(new Page(0, -1), queryDTO);
            List<QualityQuestionStatisticsByProblemTypeDTO> records = page.getRecords();
            if(CollectionUtil.isNotEmpty(records)){
                records.stream().forEach(p->{
                    if(null == p.getPercent()){
                        p.setPercent(0d);
                    }else{
                        p.setPercent(NumberUtil.mul(p.getPercent(),100d,2));
                    }
                    p.setPercentStr(p.getPercent() + "%");
                });
            }
            String keyValue = "问题分类:fullName,占比:percentStr,全部:allCount,一般:level1Count,严重:level2Count,紧要:level3Count,合格:state3";
            String title = "按问题分类 导出数据";
            String fileName = title + ".xls";
            try {
                OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
                ExcelTools.exportExcel(outputStream, keyValue, records, ExcelConstant.XLS, title);
                response.flushBuffer();
                outputStream.close();
            } catch (IOException e) {
                log.error("excel导出失败", e);
                throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
            } catch (Exception e) {
                log.error("excel导出失败", e);
                throw new RuntimeException("excel导出失败！" + e.getMessage());
            }
        }else{
            IPage<QualityQuestionStatisticsByCheckPartDTO> page = baseMapper
                .countQualityQuestionByCheckPart(new Page(0, -1), queryDTO);
            List<QualityQuestionStatisticsByCheckPartDTO> records = page.getRecords();
            if(CollectionUtil.isNotEmpty(records)){
                records.stream().forEach(p->{
                    if(null == p.getPercent()){
                        p.setPercent(0d);
                    }else{
                        p.setPercent(NumberUtil.mul(p.getPercent(),100d,2));
                    }
                    p.setPercentStr(p.getPercent() + "%");
                });
            }
            String keyValue = "部位:fullName,全部:allCount,待整改:state1,待复核:state2,合格:state3,不合格:state4,占比:percentStr";
            String title = "按检查部位 导出数据";
            String fileName = title + ".xls";
            try {
                OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
                ExcelTools.exportExcel(outputStream, keyValue, records, ExcelConstant.XLS, title);
                response.flushBuffer();
                outputStream.close();
            } catch (IOException e) {
                log.error("excel导出失败", e);
                throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
            } catch (Exception e) {
                log.error("excel导出失败", e);
                throw new RuntimeException("excel导出失败！" + e.getMessage());
            }
        }


    }

}

